package cate.game.role.pvp.minecraft.po;

import cate.common.table.d.*;
import cate.common.table.pvp.minecraft.mine_area_base.MinecraftMineAreaBaseRow;
import cate.common.table.pvp.minecraft.mine_area_floor.MinecraftMineAreaFloorRow;
import cate.common.util.TimeTool;
import cate.game.framework.ThreadShare;
import cate.game.play.param.FightParam;
import cate.game.play.param.HpExtend;
import cate.game.play.part.BattleHero;
import cate.game.play.part.FightSide;
import cate.game.play.part.PlaySide;
import cate.game.play.proce.play.PlayPO;
import cate.game.play.vo.HeroVO;
import cate.game.play.vo.RoleSnapShotVO;
import cate.game.pvp.minecraft.MinecraftConstants;
import cate.game.pvp.minecraft.data.MinecraftPvpRecord;
import cate.game.res.MixRes;
import cate.game.res.MixResAdder;
import cate.game.res.MixResConsumer;
import cate.game.role.Role;
import cate.game.role.farm.AbstractFarm;
import cate.game.role.farm.TimeBasedPlayTimes;
import cate.game.role.farm.island.po.HeroState;
import cate.game.role.fight.FuncPosition;
import cate.game.role.fight.Position;
import cate.game.role.pvp.minecraft.MinecraftMineAreaFTC;
import cate.game.role.pvp.minecraft.msg.MinecraftMineAreaFightRecordsResp;
import cate.game.role.pvp.minecraft.msg.MinecraftMineAreaFightResultResp;
import cate.game.role.pvp.minecraft.msg.MinecraftMineAreaMainInfoResp;
import cate.game.role.pvp.minecraft.msg.MinecraftMineAreaNewFightRecordResp;
import com.fasterxml.jackson.annotation.JsonIgnore;
import easy.java.dev.note.NoteClass;
import easy.java.dev.note.NoteField;
import easy.java.practice.errorcode.EcResult;
import org.springframework.data.annotation.Transient;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import cate.game.pvp.minecraft.MinecraftMessagingModule.CrossTryFightPointBack;

import static cate.game.role.pvp.minecraft.MinecraftMineAreaFTC.FIGHT_TYPE_MONSTER;
import static cate.game.role.pvp.minecraft.MinecraftMineAreaFTC.FIGHT_TYPE_PLAYER;

@NoteClass("矿洞争霸-采集区数据")
public class MinecraftGatherPO extends AbstractFarm {
    @NoteField("历史查看层")
    public int historyLayer;
    @NoteField("今日保护卡使用次数")
    public int protectUsedTime;
    @NoteField("保护结束时间")
    public long protectTime;
    @NoteField("占领AND掠夺次数")
    public TimeBasedPlayTimes fightTimes;
    @NoteField("挑战记录")
    public List<MinecraftPvpRecord> fightRecords;

    @NoteField(value = "当前占用的圣器列表")
    public List<Integer> usedHallows;
    @NoteField(value = "当前占用的英雄原型ID列表")
    public List<Integer> usedHeroProtoIds;

    @Transient
    @JsonIgnore
    @NoteField("当前关注的层数")
    public transient int watchingLayer;

    @JsonIgnore
    @NoteField("战斗中的层数")
    public int fightingLayer;
    @JsonIgnore
    @NoteField("战斗中的矿点配置ID")
    public int fightingTid;
    @JsonIgnore
    @NoteField("战斗中的敌方信息")
    public List<PlaySide> fightingPlaySides;
    @JsonIgnore
    @NoteField("战斗中的敌方血量信息")
    public List<HeroState> fightingHeroStates;
    @JsonIgnore
    @NoteField("结算的敌方血量信息")
    public List<HeroState> resultHeroStates;
    @NoteField("剧本UID->OpenApi生成的ID")
    public Map<String, Long> playUidToOpenIds;

    @Transient
    @JsonIgnore
    private transient final Map<String, Long> operationLimitTimes = new HashMap<>();

    @Override
    public void initialize(Role role) {
        super.initialize(role);
        if (fightTimes != null) {
            fightTimes.setup(MinecraftConstants.MAX_FIGHT_NUM,
                    MinecraftConstants.FIGHT_ADD_INTERVAL_MINUTE * TimeTool.TimeCons.MINUTE);
        }
        if (fightRecords == null) {
            fightRecords = new ArrayList<>();
        }

        if (usedHallows == null) {
            usedHallows = new ArrayList<>();
        }
        if (usedHeroProtoIds == null) {
            usedHeroProtoIds = new ArrayList<>();
        }

        if (fightingPlaySides == null) {
            fightingPlaySides = new ArrayList<>();
        }
        if (fightingHeroStates == null) {
            fightingHeroStates = new ArrayList<>();
        }
        if (resultHeroStates == null) {
            resultHeroStates = new ArrayList<>();
        }
        if (playUidToOpenIds == null) {
            playUidToOpenIds = new HashMap<>();
        }
    }

    @Override
    public int getFuncId() {
        return GDFunc.MINECRAFT_GATHER;
    }

    @Override
    public int getFightFuncId() {
        return GDFunc.MINECRAFT_GATHER;
    }

    @Override
    public void onAfterOpen() {
        if (fightTimes == null) {
            fightTimes = new TimeBasedPlayTimes(MinecraftConstants.INIT_FIGHT_NUM);
            fightTimes.setup(MinecraftConstants.MAX_FIGHT_NUM,
                    MinecraftConstants.FIGHT_ADD_INTERVAL_MINUTE * TimeTool.TimeCons.MINUTE);
        }
        noticeUpdate();
    }

    @Override
    public void offline() {
        super.offline();
        watchingLayer = 0;
    }

    @Override
    public void onDaySpan(boolean silence) {
        super.onDaySpan(silence);
        if (fightTimes != null) {
            fightTimes.addCurrent(MinecraftConstants.FIGHT_ADD_DAILY);
        }
        protectUsedTime = 0;
        if (!silence) {
            noticeUpdate();
        }
    }

    /**
     * 循环
     */
    public void tick() {
        if (fightTimes != null) {
            fightTimes.tick();
        }
    }

    /**
     * 检测超时
     *
     * @param operationMark 操作标记
     * @param limit 限制时间ms
     * @param send 是否发送
     * @return 是否驳回消息
     */
    private boolean checkOperationDeny(String operationMark, long limit, boolean send) {
        long nowTime = System.currentTimeMillis();
        if (operationLimitTimes.containsKey(operationMark) && operationLimitTimes.get(operationMark) > nowTime) {
            if (send) {
                role.getGame().notice.message(role, "请求过于频繁!");
            }
            return true;
        }
        operationLimitTimes.put(operationMark, nowTime + limit);
        return false;
    }

    /**
     * 检测超时
     *
     * @param operationMark 操作标记
     * @param limit 限制时间ms
     * @return 是否驳回消息
     */
    private boolean checkOperationDeny(String operationMark, long limit) {
        return checkOperationDeny(operationMark, limit, true);
    }

    /**
     * 角色上线初始化
     */
    public void onRoleInit() {
        // 角色上线默认会同步占用信息 所以不用在这里发包
        // noticeUpdate();
        noticePvpRecords();
        role.getPvp().minecraft.sendMinecraftMineAreaState();
        role.getGame().pvp.minecraft.getMessagingModule().roleEnterSync(role);
    }

    /**
     * 同步信息到前端
     */
    public void noticeUpdate() {
        role.sendNow(new MinecraftMineAreaMainInfoResp(this));
    }

    /**
     * 同步PVP记录到前端
     */
    public void noticePvpRecords() {
        role.sendNow(new MinecraftMineAreaFightRecordsResp(this));
    }

    /**
     * 更新占用的原型ID列表
     *
     * @param idList 原型ID列表
     */
    public void updateUsedHeroProtoIds(List<Integer> hallows, List<Integer> idList) {
        usedHallows.clear();
        usedHallows.addAll(hallows);
        usedHeroProtoIds.clear();
        usedHeroProtoIds.addAll(idList);
        if (role.getStatus().isOnline()) {
            noticeUpdate();
        }
    }

    /**
     * 查看概览
     */
    public void overview() {
        role.getGame().pvp.minecraft.getMessagingModule().handleOverview(role);
    }

    /**
     * 是否禁止进入该层
     *
     * @param layer 矿层
     */
    private boolean denyLayer(int layer) {
        MinecraftMineAreaFloorRow row = role.getGame().table.minecraft.mine_area_floor.get(layer);
        if (row == null) {
            return true;
        }
        if (role.getBase().level < row.levelNeed) {
            role.getGame().notice.message(role, "等级不足");
            return true;
        }
        if (role.getBase().power < row.powerNeed) {
            role.getGame().notice.message(role, "战力不足");
            return true;
        }
        return false;
    }

    /**
     * 查看矿场层内信息
     *
     * @param layer 层数
     */
    public void viewLayer(int layer) {
        if (checkOperationDeny("view-layer", 200)) {
            return;
        }
        if (denyLayer(layer)) {
            return;
        }
        historyLayer = layer;
        watchingLayer = layer;
        role.getGame().pvp.minecraft.getMessagingModule().handleViewLayer(role, layer);
    }

    /**
     * 停止查看矿场层内信息
     */
    public void stopViewLayer() {
        watchingLayer = 0;
    }

    /**
     * 查看我的点位信息
     *
     * @param detail 是否细节
     */
    public void viewMyPoints(boolean detail) {
        if (checkOperationDeny("view-my-points", 200)) {
            return;
        }
        role.getGame().pvp.minecraft.getMessagingModule().handleViewMyPoints(role, detail);
    }

    /**
     * 查看点位详细信息
     *
     * @param layer 层数
     * @param tid 配置ID
     */
    public void viewPointDetail(int layer, int tid) {
        if (checkOperationDeny("view-point-detail", 200)) {
            return;
        }
        if (denyLayer(layer)) {
            return;
        }
        role.getGame().pvp.minecraft.getMessagingModule().handleViewPointDetail(role, layer, tid);
    }

    /**
     * 清空战斗信息
     */
    public void clearFightingInfos() {
        fightingLayer = 0;
        fightingTid = 0;
        fightingPlaySides.clear();
        fightingHeroStates.clear();
        resultHeroStates.clear();
        endFighting();
    }

    /**
     * 前端发起战斗
     *
     * @param layer 层数
     * @param tid   配置ID
     */
    public EcResult<Void> onClientFightPoint(int layer, int tid) {
        EcResult<Void> r = new EcResult<>();
        if (checkOperationDeny("try-fight", 500, false)) {
            return r.fail("请求过于频繁!");
        }
        if (denyLayer(layer)) {
            return r.success();
        }
        FuncPosition funcPosition = role.getFight().getFuncPositions(GDFunc.MINECRAFT_GATHER);
        if (funcPosition == null) {
            return r.fail("未找到布阵");
        }
        if (role.getFight().funcPositionContainsHallow(funcPosition, usedHallows)) {
            return r.fail("不得使用已经占用的圣器");
        }
        if (role.getFight().funcPositionContainsHeroProtoId(funcPosition, usedHeroProtoIds)) {
            return r.fail("不得使用已经占用的英雄");
        }
        if (fighting) {
            return r.fail("战斗中,无法重复作战");
        }
//        if (!role.getPvp().minecraft.challengePO.checkLayerOpened(layer)) {
//            return r.fail("当前层未开启");
//        }
        r = fightTimes.available();
        if (!r.ok()) {
            return r;
        }
        // 尝试前往跨服拉取战斗数据
        role.getGame().pvp.minecraft.getMessagingModule().tryFight(role, layer, tid);
        // 提前进入战斗状态 如果跨服战斗失败则回调取消
        startFighting();
        return r.success();
    }

    /**
     * 跨服战斗结果回调
     *
     * @param back 回调数据
     */
    public void onCrossTryFightBack(CrossTryFightPointBack back) {
        if (!back.result.ok()) {
            endFighting();
            if (role.getStatus().isOnline()) {
                role.getGame().notice.message(role, back.result);
            }
            return;
        }
        onCrossFightPoint(back.layer, back.tid, back.playSides, back.heroStates);
    }

    /**
     * 跨服发起挑战
     *
     * @param layer      层数
     * @param tid        配置ID
     * @param playSides  玩家方信息
     * @param heroStates 英雄血量
     */
    public void onCrossFightPoint(int layer, int tid, List<PlaySide> playSides, List<HeroState> heroStates) {
        fightingLayer = layer;
        fightingTid = tid;
        fightingPlaySides.clear();
        if (playSides != null) {
            playSides.forEach(playSide -> fightingPlaySides.add(playSide.copy()));
        }
        fightingHeroStates.clear();
        resultHeroStates.clear();
        if (heroStates != null) {
            heroStates.forEach(heroState -> {
                fightingHeroStates.add(heroState.copy());
                resultHeroStates.add(heroState.copy());
            });
        }
        challenge(GDPosition.DEFAULT_POS_NUM);
    }

    /**
     * 挑战
     *
     * @param posNum 队伍编号
     */
    public EcResult<Void> challenge(byte posNum) {
        byte fightType = fightingPlaySides.isEmpty() ? FIGHT_TYPE_MONSTER : FIGHT_TYPE_PLAYER;
        EcResult<Void> r;
        switch (fightType) {
            case FIGHT_TYPE_MONSTER:
                r = challengeMonster(posNum);
                break;
            case FIGHT_TYPE_PLAYER:
                r = challengePlayer(posNum);
                break;
            default:
                r = new EcResult<Void>().fail("fight type error");
                break;
        }
        if (!r.ok()) {
            // 通知跨服取消战斗状态
            role.getGame().pvp.minecraft.getMessagingModule().fightResultReport(role,
                    fightingLayer,
                    fightingTid,
                    false,
                    0L,
                    0L,
                    null,
                    null,
                    null);
            role.getGame().notice.message(role, r);
            clearFightingInfos();
        }
        return r;
    }

    /**
     * 检测是否全部阵亡
     *
     * @param playSide   玩家方
     * @param heroStates 英雄状态
     */
    private boolean checkAllDie(PlaySide playSide, List<HeroState> heroStates) {
        if (heroStates == null || heroStates.isEmpty()) {
            return false;
        }
        for (BattleHero battleHero : playSide.hs) {
            HeroVO hero = battleHero.hero;
            if (hero != null) {
                boolean find = false;
                for (HeroState state : heroStates) {
                    if (state.heroUid.equals(hero.uid)) {
                        if (state.isDead()) {
                            find = true;
                        } else {
                            return false;
                        }
                    }
                }
                if (!find) {
                    return false;
                }
            }
        }
        return true;
    }

    /**
     * 挑战野怪
     *
     * @param posNum 队伍编号
     * @return 挑战结果
     */
    private EcResult<Void> challengeMonster(byte posNum) {
        EcResult<Void> r = new EcResult<>();
        MinecraftMineAreaBaseRow config = role.getGame().table.minecraft.mine_area_base.get(fightingTid);
        if (config == null) {
            return r.fail("找不到配置");
        }
        if (!checkPosition(config.getPosNum())) {
            return r.fail("当前关卡需要" + config.getPosNum() + "支队伍");
        }
        // 挑战模式
        EcResult<FightSide> fsr = role.getGame().fight.side.createFightSideByCode(GDFight.Team.B, config.getInsCode(posNum));
        if (!fsr.ok()) {
            return r.fail(fsr.message);
        }
        MinecraftMineAreaFTC context = new MinecraftMineAreaFTC(role, fightingLayer, fightingTid, FIGHT_TYPE_MONSTER, posNum);
        context.funcId = GDFunc.MINECRAFT_GATHER;
        context.playStory.level = fightingTid;
        context.playStory.playMax = config.getPosNum();
        // 设置前置战斗胜利
        for (int i = 1; i < context.posNum; i++) {
            context.playStory.preWinner.add(GDFight.Team.A);
        }
        EcResult<PlayPO> fightRes = role.getGame().play.startByRole(role, context, fsr.data);
        if (!fightRes.ok()) {
            return r.fail(fightRes.message);
        }
        return r.success();
    }

    /**
     * 检测英雄布阵
     *
     * @param posNum 布阵数
     * @return 检测结果
     */
    protected boolean checkPosition(int posNum) {
        for (int i = 1; i <= posNum; ++i) {
            Position position = role.getFight().getPosition(getFightFuncId(), posNum);
            if (position == null || position.grids.isEmpty()) {
                return false;
            }
        }
        return true;
    }

    /**
     * 挑战玩家
     *
     * @param posNum 队伍编号
     * @return 挑战结果
     */
    private EcResult<Void> challengePlayer(byte posNum) {
        EcResult<Void> r = new EcResult<>();
        if (posNum > fightingPlaySides.size()) {
            return r.fail("超出队列上限");
        }
        PlaySide playSide = fightingPlaySides.get(posNum - 1);
        if (checkAllDie(playSide, fightingHeroStates)) {
            return challengePlayer((byte) (posNum + 1));
        }
        MinecraftMineAreaFTC context = new MinecraftMineAreaFTC(role, fightingLayer, fightingTid, FIGHT_TYPE_PLAYER, posNum);
        context.funcId = GDFunc.MINECRAFT_GATHER;
        context.playStory.level = fightingTid;
        context.playStory.playMax = fightingHeroStates.size();
        // 设置前置战斗胜利
        for (int i = 1; i < context.posNum; i++) {
            context.playStory.preWinner.add(GDFight.Team.A);
        }
        // 守方血量继承
        FightParam fightParam = new FightParam();
        fightParam.sideB.hpExtend = buildHpExtend(playSide, fightingHeroStates);
        context.param = fightParam;
        // 守方战斗方构建
        FightSide fightSideB = role.getGame().fight.side.createFightSideByPlaySide(GDFight.Team.B, playSide);
        EcResult<PlayPO> fightResult = role.getGame().play.startByRole(role, context, fightSideB);
        if (!fightResult.ok()) {
            return r.fail(fightResult.message);
        }
        return r.success();
    }

    /**
     * 构建血量继承
     *
     * @param playSide           对手阵容
     * @param fightingHeroStates 血量状态
     */
    private HpExtend buildHpExtend(PlaySide playSide, List<HeroState> fightingHeroStates) {
        HpExtend hpExtend = new HpExtend();
        if (fightingHeroStates != null) {
            for (BattleHero battleHero : playSide.hs) {
                fightingHeroStates.stream().filter(heroState -> heroState.heroUid.equals(battleHero.hero.uid))
                        .forEach(heroState -> hpExtend.recordByHeroUid(heroState.heroUid, heroState.hpRate));
            }
        }
        return hpExtend;
    }

    /**
     * 构建自身的阵容列表
     */
    public List<PlaySide> buildSelfPlaySides() {
        List<PlaySide> playSides = new ArrayList<>();
        FuncPosition funcPosition = role.getFight().getFuncPositions(GDFunc.MINECRAFT_GATHER);
        if (funcPosition != null) {
            funcPosition.positions.forEach(position -> {
                EcResult<PlaySide> r = role.getGame().fight.side.createPlaySideByRole(role,
                        GDFunc.MINECRAFT_GATHER, position.posNum);
                if (r.ok()) {
                    playSides.add(r.data);
                }
            });
        }
        return playSides;
    }

    /**
     * 记录剧本UID对应OpenApi生成ID
     *
     * @param uid 剧本UID
     * @param id OpenApi生成ID
     */
    public void recordPlayUidToOpenId(String uid, Long id) {
        playUidToOpenIds.put(uid, id);
    }

    /**
     * 处理跨服战斗结果返回
     *
     * @param r 结果返回
     */
    public void onCrossBackFightResultResp(byte fightType, MixRes lostRes, long protectTime, EcResult<MinecraftMineAreaFightResultResp> r) {
        if (r == null || r.data == null) {
            return;
        }
        if (!r.ok()) {
            role.getGame().notice.message(role, r);
            return;
        }
        fightTimes.useCurrent();
        this.protectTime = protectTime;
        noticeUpdate();
        MinecraftMineAreaFightResultResp resp = r.data;
        if (resp.reward != null && !resp.reward.isEmpty()) {
            new MixResAdder().setRes(resp.reward)
                    .setOperation(GDOperation.MINECRAFT_MINE_AREA_FIGHT_REWARD)
                    .setDialogReward(false)
                    .setSendMailWhenFull(true)
                    .exe(role);
        }
        role.sendNow(resp);
        // 生成战报
        if(resp.win){
            role.getHistory().action.minecraftWin();
        }
        if (resp.reports != null && resp.reports.size() > 0) {
            RoleSnapShotVO dest = resp.reports.get(0).b.snapshot;
            MinecraftPvpRecord record = new MinecraftPvpRecord();
            record.recordTime = System.currentTimeMillis();
            record.winner = resp.win ? GDFight.Team.A : GDFight.Team.B;
            if (record.winner == GDFight.Team.A || fightType == FIGHT_TYPE_PLAYER) {
                record.snapshotA = resp.reports.get(0).a.snapshot;
                record.snapshotB = fightType == FIGHT_TYPE_PLAYER ? dest : null;
                record.replayOpenIds = new ArrayList<>(resp.reports.size());
                resp.reports.forEach(playReportVO -> {
                    if (playUidToOpenIds.containsKey(playReportVO.uid)) {
                        record.replayOpenIds.add(playUidToOpenIds.get(playReportVO.uid));
                    }
                });
                record.tid = resp.tid;
                record.robbedItems = lostRes == null ? new MixRes() : lostRes;
                addPvpRecord(record);
                if (fightType == FIGHT_TYPE_PLAYER && dest != null) {
                    if (dest.base.srvId == role.getGame().config.srvId) {
                        Role destRole = role.getGame().role.getRole(dest.uid);
                        if (destRole != null) {
                            ThreadShare.instance().exe(destRole, () -> destRole.getPvp().minecraft.gatherPO.addPvpRecord(record));
                        }
                    } else {
                        // 同步PVP记录
                        role.getGame().pvp.minecraft.getMessagingModule().transferPvpRecord(dest.base.srvId, record);
                    }
                }
            }
        }
        playUidToOpenIds.clear();
    }

    /**
     * 添加战斗记录
     *
     * @param record 战斗记录
     */
    public void addPvpRecord(MinecraftPvpRecord record) {
        fightRecords.add(record);
        if (fightRecords.size() > 30) {
            int delNum = fightRecords.size() - 30;
            fightRecords.subList(0, delNum).clear();
        }
        if (role.getStatus().isOnline()) {
            // 发送新战报到前端
            role.sendNow(new MinecraftMineAreaNewFightRecordResp(record));
        }
    }

    /**
     * 领取挂机奖励
     *
     * @param layer 层数
     * @param tid 配置ID
     */
    public void getHangReward(int layer, int tid) {
        role.getGame().pvp.minecraft.getMessagingModule().handleGetHangReward(role, layer, tid);
    }

    /**
     * 跨服回复领取挂机奖励
     *
     * @param result 结果
     */
    public void onCrossBackGetHangReward(EcResult<MixRes> result) {
        if (checkOperationDeny("get-hang-reward", 300)) {
            return;
        }
        if (!result.ok()) {
            role.getGame().notice.message(role, result);
        } else {
            role.getHistory().action.minecraftHangReward();
            new MixResAdder().setRes(result.data)
                    .setOperation(GDOperation.MINECRAFT_MINE_AREA_HANG_REWARD)
                    .setDialogReward(true)
                    .setSendMailWhenFull(true)
                    .exe(role);
        }
    }

    /**
     * 矿点保护
     */
    public void protectPoint() {
        if (checkOperationDeny("protect-point", 200)) {
            return;
        }
        if (protectUsedTime >= MinecraftConstants.PROTECT_DAILY_MAX) {
            role.getGame().notice.message(role, "今日使用保护卡次数已达上限!");
            return;
        }
        MixRes costRes = new MixRes(MinecraftConstants.PROTECT_COST_STR);
        if (costRes.isEmpty()) {
            role.getGame().notice.message(role, "保护卡消耗配置错误!");
            return;
        }
        EcResult<?> r = costRes.consumeCheck(role);
        if (!r.ok()) {
            role.getGame().notice.message(role, r);
            return;
        }
        role.getGame().pvp.minecraft.getMessagingModule().handleProtectPoint(role);
    }

    /**
     * 跨服矿点保护返回
     *
     * @param r 处理结果
     */
    public void onCrossProtectPointBack(EcResult<Long> r) {
        if (!r.ok()) {
            role.getGame().notice.message(role, r);
        } else {
            protectUsedTime++;
            protectTime = r.data;
            noticeUpdate();
            MixRes costRes = new MixRes(MinecraftConstants.PROTECT_COST_STR);
            role.log.setOperation(GDOperation.MINECRAFT_MINE_AREA_PROTECT);
            costRes.consume(role);
            role.log.clearOperation();
        }
    }

    /**
     * 放弃矿点
     *
     * @param layer 层数
     * @param tid 配置ID
     */
    public void giveUpPoint(int layer, int tid) {
        if (checkOperationDeny("give-up-point", 200)) {
            return;
        }
        if (denyLayer(layer)) {
            return;
        }
        role.getGame().pvp.minecraft.getMessagingModule().handleGiveUpPoint(role, layer, tid);
    }

    /**
     * 跨服放弃矿点返回
     *
     * @param r 处理结果
     */
    public void onCrossGiveUpPointBack(EcResult<MixRes> r) {
        if (!r.ok()) {
            role.getGame().notice.message(role, r);
        } else {
            if (r.data != null && !r.data.isEmpty()) {
                new MixResAdder().setRes(r.data)
                        .setOperation(GDOperation.MINECRAFT_MINE_AREA_HANG_REWARD)
                        .setDialogReward(true)
                        .setSendMailWhenFull(true)
                        .exe(role);
            }
        }
    }

    /**
     * 添加挑战次数
     */
    public void addFightTime() {
        if (checkOperationDeny("add-fight-time", 200)) {
            return;
        }
        if (!role.getPvp().minecraft.isOpen()) {
            role.getGame().notice.message(role, "功能未开启");
            return;
        }
        if (fightTimes == null) {
            role.getGame().notice.message(role, "功能未开启!");
            return;
        }
        if (fightTimes.max()) {
            role.getGame().notice.message(role, "挑战次数已达到上限");
            return;
        }
        MixRes costRes = new MixRes(MinecraftConstants.FIGHT_ADD_COST_STR);
        if (costRes.isEmpty()) {
            role.getGame().notice.message(role, "增加挑战次数消耗配置错误!");
            return;
        }
        new MixResConsumer<Void>().res(costRes)
                .tips(true)
                .operation(GDOperation.MINECRAFT_MINE_AREA_ADD_FIGHT, 0)
                .success(role -> {
                    fightTimes.addCurrent(1);
                    role.getPvp().minecraft.gatherPO.noticeUpdate();
                    return null;
                })
                .exe(role);
    }
}
